package jp.sourceforge.talisman.mds.cluster;

/*
 * $Id: HierarchicalClusteringParameter.java,v 1.1 2009/09/12 05:06:01 weiwei Exp $
 */

import jp.sourceforge.talisman.mds.Item;
import jp.sourceforge.talisman.mds.distance.ClusterDistanceAlgorithm;
import jp.sourceforge.talisman.mds.distance.ClusterDistanceCalculator;
import jp.sourceforge.talisman.mds.distance.DistanceCalculatorFactory;
import jp.sourceforge.talisman.mds.distance.DistanceCalculatorNotFoundException;
import jp.sourceforge.talisman.mds.distance.ItemDistanceAlgorithm;
import jp.sourceforge.talisman.mds.distance.ItemDistanceCalculator;

/**
 * 
 * @author Haruaki Tamada
 * @version $Revision: 1.1 $ 
 */
public class HierarchicalClusteringParameter extends ClusteringParameter{
    private ClusterDistanceCalculator clusterDistanceCalculator;

    public HierarchicalClusteringParameter(int numberOfCluster){
        setNumberOfCluster(numberOfCluster);
    }

    public HierarchicalClusteringParameter(int numberOfCluster, ItemDistanceCalculator id, ClusterDistanceCalculator cdc){
        setNumberOfCluster(numberOfCluster);
        setDistanceCalculator(id);
        setClusterDistanceCalculator(cdc);
        cdc.setItemDistanceCalculator(id);
    }

    public HierarchicalClusteringParameter(int numberOfCluster, ItemDistanceAlgorithm ida, ClusterDistanceAlgorithm cda){
        setNumberOfCluster(numberOfCluster);
        setDistanceCalculator(ida);
        setClusterDistanceCalculator(cda);
        getClusterDistanceCalculator().setItemDistanceCalculator(ida);
    }

    public void setClusterDistanceCalculator(ClusterDistanceAlgorithm algorithm){
        if(algorithm == null){
            throw new NullPointerException();
        }
        if(getDistanceCalculator() == null){
            throw new NullPointerException("distance calculator is required");
        }
        try{
            assert getDistanceCalculator() != null;

            setClusterDistanceCalculator(
                DistanceCalculatorFactory.getInstance().getClusterDistanceCalculator(
                    algorithm, getDistanceCalculator().getAlgorithm()
                )
            );
        } catch(DistanceCalculatorNotFoundException e){
            // If getDistanceCalculator is null, then DistanceCalculatorNotFoundException was thrown.
            // However, null check of getDistanceCalculator is executed, hence, this catch statement never reach.
            throw new InternalError();
        }
    }

    public void setClusterDistanceCalculator(ClusterDistanceCalculator cdc){
        if(cdc == null){
            throw new NullPointerException();
        }
        this.clusterDistanceCalculator = cdc;
    }

    public ClusterDistanceCalculator getClusterDistanceCalculator(){
        return clusterDistanceCalculator;
    }

    public void setDistanceCalculator(ItemDistanceCalculator idc){
        super.setDistanceCalculator(idc);
        if(clusterDistanceCalculator != null){
            clusterDistanceCalculator.setItemDistanceCalculator(idc);
        }
    }

    @Override
    public boolean isValid(Item[] items){
        return items.length >= getNumberOfCluster() &&
        getClusterDistanceCalculator() != null &&
        getDistanceCalculator() != null;
    }
}
